home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-17 | 23.5 KB | 884 lines | [TEXT/KAHL] |
- //
- // alloc.c - Written by Glenn L. Austin
- // Copyright © 1995 Symantec Corporation. All Rights Reserved.
- //
- // Higher-performance, better heap management & validity checking.
- // Also returns memory to the Macintosh if it isn't in use!!!
- //
- // Revision history:
- //
- // Release 1.0.10
- // -------------
- // * Added functionality for big blocks to automatically get returned to
- // the application zone, regardless of the setting of gRestoreMemToHeap.
- // * When allocating memory, I check to see if the existing zone(s) could
- // satisfy the request before checking if the size is greater than the
- // crossover size.
- //
- // Release 1.0.9
- // -------------
- // * I missed yet one more assignment in 1.0.8 when the next block isn't
- // a free block when freeing.
- //
- // Release 1.0.8
- // -------------
- // * I missed an assignment in 1.0.7 when fixing the bug in free where, if the
- // next block was the end of zone, it wasn't setting the size correctly for
- // the newly freed block.
- // * I now provide an AppleScript to update the ANSI libraries for both TPM and
- // SPM to use alloc_gla.c instead of alloc.c.
- //
- // Release 1.0.7
- // -------------
- // * There was a bug in free when the block that was being freed was the last
- // block in a zone. It wasn't getting combined with the previous block if
- // the previous block was also a free block. (thanks DF)
- //
- // Release 1.0.6
- // -------------
- // * Commented out the _UseAssert_ and _Debug_Alloc_GLA__ macros, since they
- // shouldn't have been uncommented in the final version.
- //
- // Release 1.0.5
- // -------------
- // * Bug fixed in alloc when the block is getting initialized. It was allocating
- // space for a block of the specified size, but was initializing for a maximum
- // block size of sizeof(MemBlock) bytes smaller.
- // * Bug fixed in calculating the 8 byte size (alignment). It was adding 8, which
- // could allocate 8 bytes more than was necessary, if the requested size was
- // already a multiple of 8.
- //
- // Release 1.0.4
- // -------------
- // * Bug fixed in realloc when the block following this block was the end
- // of the zone, which is a special "free" block. Now special casing for
- // end of zone.
- // * Bug fixed in realloc when the block following this block was free, but
- // wasn't large enough to satisfy the request for the resize. Now mallocs
- // a new block if this is the case.
- // * Made sure all asserts were inside conditional compile flag.
- // * Added CheckBlocks routine for testing allocations without I/O.
- // * Sizes are now a multiple of 8, which means that addresses should also
- // be a multiple of 8. This will improve performance on PowerPC with
- // doubles.
- //
- // Release 1.0.3
- // -------------
- // * Improved realloc performance when the next block is a free block since
- // realloc will now manipulate the free block size rather than moving the
- // current block if it is growing.
- // * Fixed many annoying bugs in realloc when the new size would make the
- // size of the following free block smaller than 2 bytes.
- //
- // Release 1.0.2
- // -------------
- // * Fixed problems with blocks larger than gMaxBlockSize. They were still
- // marked as free blocks, even though they were in use.
- //
- // Release 1.0.1
- // -------------
- // * Fixed problems with splitting a free block when the first free block
- // would be close to the same size as the block being split. The second
- // block header would overwrite the beginne next block header.
- //
- // Release 1.0
- // -----------
- // * Initial release on Symantec C++ 8.0 CD
- //
-
- //#define _UseAssert_
- //#define NDEBUG
- //#define __DUMPBLOCKS__ 0
- //#define _Debug_Alloc_GLA__
-
- #pragma options(assign_registers)
- #pragma options(honor_register)
- #pragma options(defer_adjust)
- #pragma options(redundant_loads)
-
- Boolean DumpBlocks(void);
-
- #ifdef _UseAssert_
- #include <assert.h>
- #ifdef NDEBUG
- #define assertMsg(x) ((void) 0)
- #else
- #define assertMsg(x) (__assert(#x, __FILE__, __LINE__))
- #endif
- #endif
- #ifndef __DUMPBLOCKS__
- #ifdef __Debug_Alloc_GLA__
- #define __DUMPBLOCKS__ 1
- #else
- #define __DUMPBLOCKS__ 0
- #endif
- #endif
-
- #if __DUMPBLOCKS__
- #include <stdio.h>
- #endif
- #include <stdlib.h>
-
- #include <Memory.h>
- #include <OSUtils.h>
-
- #ifndef kMaxBlockSize
- #define kMaxBlockSize 32768L
- #endif
-
- #define kEndOfZone (-1L)
- #define kZHPFlag 0x1204
- #define kBigZHPFlag 0x0313
-
- #if USES68KINLINES
- #pragma parameter __D0 TGetPtrSize(__A0)
- extern pascal Size TGetPtrSize(Ptr thePtr) = 0xA021;
- #else
- #define TGetPtrSize(p) GetPtrSize(p)
- #endif
-
- #ifdef __Debug_Alloc_GLA__
- extern Boolean __MMPrimitiveAllocate;
- #else
- Boolean __MMPrimitiveAllocate = false;
- #endif
- unsigned long gMaxBlockSize = kMaxBlockSize;
- Boolean gRestoreMemToHeap = true;
-
- void *prealloc(size_t size);
- void cleanupalloc(void);
-
- #ifdef __Debug_Alloc_GLA__
- void _free(void *p);
- #else
- void free(void *p);
- #endif
-
- #if defined(powerc) || defined (__powerc)
- #pragma options align=mac68k
- #endif
- typedef struct {
- QElemPtr qLink;
- short flag;
- short usageCounter; // number of allocated blocks in this Block
- long nextFreeOfs; // offset from qLink to first free block
- long bytesFree; // bytes free in this block
- } ZoneHeader, *ZoneHdrPtr;
- #if defined(powerc) || defined(__powerc)
- #pragma options align=reset
- #endif
-
- #if defined(powerc) || defined (__powerc)
- #pragma options align=mac68k
- #endif
- typedef struct {
- long blkSize; // in free blocks, this is negative
- long zoneOfs; // in free blocks, this is the offset to the next free block
- //char data[0]; // the address of the data in the block
- } MemBlock, *MemBlkPtr;
- #if defined(powerc) || defined(__powerc)
- #pragma options align=reset
- #endif
-
- #if defined(powerc) || defined (__powerc)
- #pragma options align=mac68k
- #endif
- typedef struct {
- short qFlags;
- QElemPtr qHead;
- QElemPtr qTail;
- long bytesInBlocks; // the number of bytes allocated from the Mac memory manager
- long bytesFree; // the number of free bytes in Zones
- } ZoneQHdr;
- #if defined(powerc) || defined(__powerc)
- #pragma options align=reset
- #endif
-
- static ZoneQHdr gAllocQueue = {0, nil, nil, 0, 0};
-
- static void *alloc(size_t size); // allocates a new entry in the malloc heap & returns the block
- // automatically makes space for the ZoneHeader and MemBlock
- // initializes ZoneHeader, first MemBlock and trailing size
-
- #ifdef __Debug_Alloc_GLA__
- void *_malloc(size_t size)
- #else
- void *malloc(size_t size)
- #endif
- {
- void *p = nil;
- register ZoneHdrPtr zhp = nil;
- register MemBlkPtr mbp = nil;
- MemBlkPtr bmbp = nil; // last mbp, so we can adjust zoneOfs
-
- #ifdef _UseAssert_
- assert((long) size >= 0); // can't create a negative size
- #else
- #ifndef NDEBUG
- if ((long) size < 0)
- DebugStr("\p••• Error during malloc! size < 0!");
- #endif
- #endif
-
- size = ((size + 7) & ~0x00000007); // round up to even 8-byte sizes!!!
-
- if ((size > gAllocQueue.bytesFree) && (size > gMaxBlockSize))
- {
- zhp = (ZoneHdrPtr) alloc(size);
- if (!zhp)
- return(nil);
- zhp->nextFreeOfs = sizeof(ZoneHeader) + sizeof(MemBlock) + size;
- zhp->flag = kBigZHPFlag;
-
- mbp = (MemBlkPtr) ((Ptr) zhp + sizeof(ZoneHeader));
- p = (void *) ((Ptr) mbp + sizeof(MemBlock));
- mbp->blkSize = size + sizeof(MemBlock);
- mbp->zoneOfs = (Ptr) zhp - (Ptr) mbp; // zoneOfs must be negative
- }
- else
- {
- if (size > gAllocQueue.bytesFree)
- zhp = nil;
- else
- zhp = (ZoneHdrPtr) gAllocQueue.qHead;
-
- while (zhp)
- {
- if (size - sizeof(MemBlock) <= zhp->bytesFree)
- {
- mbp = (MemBlkPtr) ((Ptr) zhp + zhp->nextFreeOfs);
- bmbp = nil;
- while (mbp->blkSize != kEndOfZone)
- {
- #ifndef NDEBUG
- if ((mbp->blkSize >= 0) || (mbp->blkSize & 0x00000001) || (mbp->zoneOfs <= 0))
- #ifdef _UseAssert_
- assertMsg("••• Error in malloc heap! malloc heap is corrupt! •••");
- #else
- DebugStr("\p••• Error in malloc heap! malloc heap is corrupt! •••");
- #endif
- #endif
- if (size > -mbp->blkSize - sizeof(MemBlock))
- {
- bmbp = mbp;
- mbp = (MemBlkPtr) ((Ptr) mbp + mbp->zoneOfs); // point to the next free block
- }
- else // mbp points to the free block,
- break; // bmbp points to the last free block or nil
- }
-
- if (mbp->blkSize != kEndOfZone)
- break; // zhp, mbp & bmbp are all set up now!
- }
-
- zhp = (ZoneHdrPtr) zhp->qLink;
- }
-
- if (!zhp) // need a new free zone!
- {
- zhp = (ZoneHdrPtr) alloc(gMaxBlockSize);
- if (!zhp)
- return(nil);
- mbp = (MemBlkPtr) ((Ptr) zhp + sizeof(ZoneHeader));
- bmbp = nil;
- }
-
- // now, zhp points to a valid zone, mbp points to the free block in the zhp zone
- // bmbp is nil if mpb is the first free block, otherwise it points to the last free
- // block encountered during its search for free blocks
- if (size <= -mbp->blkSize - sizeof(MemBlock))
- {
- MemBlkPtr t = (MemBlkPtr) ((Ptr) mbp + sizeof(MemBlock) + size);
-
- // need to break the free block into two pieces?
- if (size + (sizeof(MemBlock) << 1) < -mbp->blkSize)
- {
- t->zoneOfs = mbp->zoneOfs - size - sizeof(MemBlock); // points to the next free block!
- t->blkSize = size + mbp->blkSize + sizeof(MemBlock); // since blkSize is negative, this works!
- gAllocQueue.bytesFree -= sizeof(MemBlock); // needed more bytes from free space
- zhp->bytesFree -= sizeof(MemBlock);
- }
- else
- {
- t = (MemBlkPtr) ((Ptr) mbp + mbp->zoneOfs);
- size = -mbp->blkSize - sizeof(MemBlock);
- }
- if (!bmbp)
- zhp->nextFreeOfs = (Ptr) t - (Ptr) zhp; // point to the first free in zone
- else
- bmbp->zoneOfs = (Ptr) t - (Ptr) bmbp; // offset from last free to next free
- }
- mbp->blkSize = size + sizeof(MemBlock);
- mbp->zoneOfs = (Ptr) zhp - (Ptr) mbp; // zoneOfs must be negative
- p = (void *) ((Ptr) mbp + sizeof(MemBlock));
- }
-
- if (p)
- {
- gAllocQueue.bytesFree -= size;
-
- #ifndef NDEBUG
- if (!zhp)
- #ifdef _UseAssert_
- assertMsg("••• Fatal error in malloc! Malloc heap corruption! •••");
- #else
- DebugStr("\p••• Fatal error in malloc! Malloc heap corruption! •••");
- #endif
- else
- #endif
- {
- ++zhp->usageCounter;
- zhp->bytesFree -= size;
- }
- }
-
- return(p);
- }
-
- #ifdef __Debug_Alloc_GLA__
- void *_calloc(size_t count, size_t size)
- #else
- void *calloc(size_t count, size_t size)
- #endif
- {
- register size_t siz = count * size;
- register void *p = malloc(siz);
- register short *q = (short *) p;
-
- if (!p)
- return(nil);
-
- ++siz;
- siz >>= 1;
- while (siz--)
- *q++ = 0;
-
- return(p);
- }
-
- #ifdef __Debug_Alloc_GLA__
- void *_realloc(register void *oldptr, register size_t newsize)
- #else
- void *realloc(register void *oldptr, register size_t newsize)
- #endif
- {
- register MemBlkPtr mbp;
- register MemBlkPtr t;
- ZoneHdrPtr zhp;
- void *p;
- register long toCopy;
- MemBlkPtr newfr;
- long newSz = 0;
- MemBlkPtr fr;
- long freeChange = 0;
-
- #ifdef _UseAssert_
- assert((long) newsize >= 0); // can't create a negative size
- #else
- #ifndef NDEBUG
- if ((long) newsize < 0)
- DebugStr("\p••• Error during realloc! newsize < 0!");
- #endif
- #endif
-
- if (!oldptr)
- return(malloc(newsize)); // realloc(NULL, newsize) == malloc(newsize)
- else
- mbp = (MemBlkPtr) ((Ptr) oldptr - sizeof(MemBlock)); // get memory block pointer
-
- if ((mbp->blkSize <= 0) || // invalid block pointer! blkSize MUST be positive
- (mbp->zoneOfs >= 0)) // and zoneOfs must be negative!
- return(nil);
-
- newsize = ((newsize + 7) & ~0x00000007); // size must be even!
-
- toCopy = mbp->blkSize - sizeof(MemBlock); // assume newsize > old size
- if (toCopy == newsize) // newsize == old size
- return(oldptr); // return the old pointer!
-
- if (toCopy > newsize) // if attempting to copy more than the free space...
- toCopy = newsize;
-
- freeChange = mbp->blkSize - sizeof(MemBlock) - newsize;
-
- zhp = (ZoneHdrPtr) ((Ptr) mbp + mbp->zoneOfs);
- // point to the zone header
- t = (MemBlkPtr) ((Ptr) mbp + mbp->blkSize);
- // point to the next block following this block
-
- // If the new block size is smaller than the old block, then shrink the block in
- // size and create (or combine) a free block following this block
- if (mbp->blkSize - sizeof(MemBlock) > newsize)
- {
- ResizeNextFree:
- newfr = (MemBlkPtr) ((Ptr) mbp + newsize + sizeof(MemBlock));
- fr = (MemBlkPtr) ((Ptr) zhp + zhp->nextFreeOfs);
-
- if (fr < mbp)
- {
- while (((Ptr) fr + fr->zoneOfs) < (Ptr) mbp)
- fr = (MemBlkPtr) ((Ptr) fr + fr->zoneOfs); // point to next free block
- }
- else
- fr = nil;
-
- p = oldptr; // block doesn't move
-
- if (t->blkSize == kEndOfZone)
- {
- if (freeChange < 0) // new size > old size
- goto NewMallocBlock;
- else // new size < old size
- {
- if (fr) // there is a previous free block!
- {
- newfr->zoneOfs = fr->zoneOfs - (long) newfr + (long) fr;
- fr->zoneOfs = (Ptr) newfr - (Ptr) fr;
- }
- else // no previous free block!
- {
- newfr->zoneOfs = zhp->nextFreeOfs - (long) newfr + (long) zhp;
- zhp->nextFreeOfs = ((Ptr) newfr - (Ptr) zhp);
- }
- newfr->blkSize = (Ptr) newfr - (Ptr) t;
- mbp->blkSize = newsize + sizeof(MemBlock);
- }
- }
- else if (t->blkSize < 0) // next block is a free block!
- {
- newSz = t->blkSize - ((Ptr) t - (Ptr) newfr);
-
- if (newSz >= 0)
- goto NewMallocBlock;
- else if (newSz >= -sizeof(MemBlock))
- {
- freeChange += sizeof(MemBlock);
- mbp->blkSize -= t->blkSize;
- if (fr) // there is a previous free block!
- fr->zoneOfs += t->zoneOfs;
- else
- zhp->nextFreeOfs += t->zoneOfs;
- }
- else
- goto SetupNewFreeBlock;
- }
- // Is there enough room to create a new free block?
- else if ((Ptr) t > ((Ptr) mbp + newsize + sizeof(MemBlock)))
- {
- newSz = ((Ptr) newfr - (Ptr) t);
-
- if (newSz < -sizeof(MemBlock))
- {
- SetupNewFreeBlock:
- if (fr) // there is a previous free block!
- {
- if (t->zoneOfs > 0) // is the next block a free block?
- newfr->zoneOfs = t->zoneOfs + (Ptr) t - (Ptr) newfr;
- else
- newfr->zoneOfs = fr->zoneOfs - (long) newfr + (long) fr;
- fr->zoneOfs = ((Ptr) newfr - (Ptr) fr);
- }
- else // no previous free block!
- {
- if (t->zoneOfs > 0)
- newfr->zoneOfs = t->zoneOfs + ((Ptr) t - (Ptr) newfr);
- else
- newfr->zoneOfs = zhp->nextFreeOfs - (long) newfr + (long) zhp;
- zhp->nextFreeOfs = ((Ptr) newfr - (Ptr) zhp);
- }
- newfr->blkSize = newSz;
- mbp->blkSize = newsize + sizeof(MemBlock);
- }
- else
- freeChange = 0;
- }
- }
- // Otherwise the new block size is larger than the old block, so create a new block
- // and copy the contents of the old block to the new block, then dispose the old block.
- else
- {
- if (t->blkSize < 0) // next block is a free block!
- goto ResizeNextFree;
- else
- {
- NewMallocBlock:
- #ifdef __Debug_Alloc_GLA__
- p = _malloc(newsize);
- #else
- p = malloc(newsize);
- #endif
- freeChange = 0;
- if (!p)
- return(nil);
- BlockMove(oldptr, p, toCopy); // copy the contents of the old block to the new block
- #ifdef __Debug_Alloc_GLA__
- _free(oldptr);
- #else
- free(oldptr);
- #endif
- }
- }
-
- gAllocQueue.bytesFree += freeChange;
- zhp->bytesFree += freeChange;
-
- return(p);
- }
-
- #ifdef __Debug_Alloc_GLA__
- void _free(void *p)
- #else
- void free(void *p)
- #endif
- {
- register MemBlkPtr mbp;
- register ZoneHdrPtr zhp;
-
- if (!p)
- return;
-
- mbp = (MemBlkPtr) ((Ptr) p - sizeof(MemBlock));
-
- #ifndef NDEBUG
- if ((mbp->blkSize & 0x00000001) || (mbp->zoneOfs >= 0))
- {
- #ifdef _UseAssert_
- assertMsg("••• Error during free in malloc heap! malloc heap is corrupt! •••");
- #else
- DebugStr("\p••• Error during free in malloc heap! malloc heap is corrupt! •••");
- return;
- #endif
- }
- #endif
-
- #ifndef NDEBUG
- if (mbp->blkSize <= 0) // invalid or free block!
- {
- #ifdef _UseAssert_
- assertMsg("••• Error during free -- invalid or free block! •••");
- #else
- DebugStr("\p••• Error during free -- invalid or free block! •••");
- return;
- #endif
- }
- #endif
-
- zhp = (ZoneHdrPtr) ((Ptr) mbp + mbp->zoneOfs);
- // point to the zone header
-
- // now, we know that either someone was extremely clever, or someone was extremely stupid
- // we'll verify that by checking zhp->flag
- #ifndef NDEBUG
- if ((zhp->flag != kZHPFlag) && (zhp->flag != kBigZHPFlag)) // not a valid pointer!
- {
- #ifdef _UseAssert_
- assertMsg("••• Error during free -- bad magic! •••");
- #else
- DebugStr("\p••• Error during free -- bad magic! •••");
- return;
- #endif
- }
- #endif
-
- gAllocQueue.bytesFree += mbp->blkSize - sizeof(MemBlock); // adjust bytesFree
- zhp->bytesFree += mbp->blkSize - sizeof(MemBlock);
-
- if (--zhp->usageCounter || !(gRestoreMemToHeap || (zhp->flag == kBigZHPFlag))) // still have blocks allocated in this zone
- {
- MemBlkPtr t = (MemBlkPtr) ((Ptr) mbp + mbp->blkSize); // point to the next block
- MemBlkPtr q = (MemBlkPtr) ((Ptr) zhp + zhp->nextFreeOfs); // point to the first free block
- Boolean blkCombined = false;
-
- #ifndef NDEBUG
- if ((t->blkSize ^ t->zoneOfs) >= 0)
- {
- ++zhp->usageCounter;
- gAllocQueue.bytesFree -= mbp->blkSize - sizeof(MemBlock); // adjust bytesFree
- zhp->bytesFree -= mbp->blkSize - sizeof(MemBlock);
- #ifdef _UseAssert_
- assertMsg("••• Error during free in malloc heap! End of pointer overwritten! •••");
- #else
- DebugStr("\p••• Error during free in malloc heap! End of pointer overwritten! •••");
- return;
- #endif
- }
- #endif
- if (q < mbp)
- {
- while (((Ptr) q + q->zoneOfs) < (Ptr) mbp)
- q = (MemBlkPtr) ((Ptr) q + q->zoneOfs); // point to next free block
- }
- else
- q = nil;
-
- // q now points to the previous block, which is a free block, or nil
-
- if (t->blkSize != kEndOfZone) // not last block in Block
- {
- if (t->blkSize < 0) // next block is already a free block...
- {
- mbp->zoneOfs = t->zoneOfs + mbp->blkSize; // point to next free block!
- mbp->blkSize = -(mbp->blkSize - t->blkSize);
- // add the old free block to this block!
- gAllocQueue.bytesFree += sizeof(MemBlock); // we got rid of one header
- zhp->bytesFree += sizeof(MemBlock);
- blkCombined = true;
- }
- else
- mbp->blkSize = -mbp->blkSize;
- }
- else
- mbp->blkSize = -mbp->blkSize;
-
- if (q) // there was a prior free block!
- {
- if (!blkCombined)
- mbp->zoneOfs = q->zoneOfs - ((Ptr) mbp - (Ptr) q);
- if ((((Ptr) q - q->blkSize) == (Ptr) mbp))
- {
- q->zoneOfs = mbp->zoneOfs - q->blkSize;
- q->blkSize += mbp->blkSize;
- gAllocQueue.bytesFree += sizeof(MemBlock); // we got rid of a header
- zhp->bytesFree += sizeof(MemBlock);
- }
- else
- q->zoneOfs = (Ptr) mbp - (Ptr) q;
- }
- else
- {
- if (!blkCombined)
- mbp->zoneOfs = zhp->nextFreeOfs - ((Ptr) mbp - (Ptr) zhp);
- zhp->nextFreeOfs = (Ptr) mbp - (Ptr) zhp;
- }
- }
- else
- {
- register long pSize;
-
- __MMPrimitiveAllocate = true;
- pSize = TGetPtrSize((Ptr) zhp);
- gAllocQueue.bytesInBlocks -= pSize;
- gAllocQueue.bytesFree -= zhp->bytesFree;
- Dequeue((QElemPtr) zhp, (QHdrPtr) &gAllocQueue.qFlags);
- DisposPtr((Ptr) zhp);
- __MMPrimitiveAllocate = false;
- }
- }
-
- void *prealloc(size_t size)
- {
- void *p = nil;
- register ZoneHdrPtr zhp = nil;
-
- size = ((size + 7) & ~0x00000007); // round up to even sizes!!!
-
- if (size < gMaxBlockSize)
- size = gMaxBlockSize;
-
- zhp = (ZoneHdrPtr) alloc(size);
- if (zhp)
- p = (void *) ((Ptr) zhp + sizeof(ZoneHeader) + sizeof(MemBlock));
-
- return(p);
- }
-
- void cleanupalloc(void)
- {
- register ZoneHdrPtr zhp = (ZoneHdrPtr) gAllocQueue.qHead;
-
- while (zhp)
- {
- if (!zhp->usageCounter)
- {
- register long pSize;
- ZoneHdrPtr next = (ZoneHdrPtr) zhp->qLink;
-
- __MMPrimitiveAllocate = true;
- pSize = TGetPtrSize((Ptr) zhp);
- gAllocQueue.bytesInBlocks -= pSize;
- gAllocQueue.bytesFree -= zhp->bytesFree;
- Dequeue((QElemPtr) zhp, (QHdrPtr) &gAllocQueue.qFlags);
- DisposPtr((Ptr) zhp);
- __MMPrimitiveAllocate = false;
-
- zhp = next;
- }
- else
- zhp = (ZoneHdrPtr) zhp->qLink;
- }
- }
-
- static void *alloc(register size_t size)
- {
- register long blockSize = size + sizeof(ZoneHeader) +
- (sizeof(MemBlock) << 1);
- register ZoneHdrPtr zhp;
- register MemBlkPtr mbp;
-
- __MMPrimitiveAllocate = true;
- zhp = (ZoneHdrPtr) NewPtr(blockSize);
- __MMPrimitiveAllocate = false;
-
- if (!zhp)
- return(nil);
-
- zhp->qLink = nil;
- zhp->flag = kZHPFlag;
- zhp->usageCounter = 0;
- zhp->nextFreeOfs = sizeof(ZoneHeader);
- zhp->bytesFree = size;
- mbp = (MemBlkPtr) ((Ptr) zhp + sizeof(ZoneHeader));
- mbp->zoneOfs = size + sizeof(MemBlock);
- mbp->blkSize = -mbp->zoneOfs;
- mbp = (MemBlkPtr) ((Ptr) mbp + size + sizeof(MemBlock));
- mbp->blkSize = kEndOfZone;
- mbp->zoneOfs = -kEndOfZone;
-
- gAllocQueue.bytesInBlocks += size + sizeof(ZoneHeader) + sizeof(MemBlock) + sizeof(long);
- gAllocQueue.bytesFree += size;
- Enqueue((QElemPtr) zhp, (QHdrPtr) &gAllocQueue.qFlags); // add the memory block to the queue
-
- return(zhp);
- }
-
- enum { bFreeZoneOfsBad, bUsedZoneOfsBad, bEndOfZoneOverwritten,
- bFreeOffsetIncorrect, bEndOfZoneFreeOverwritten,
-
- kFreeZoneOfsBad = (1 << bFreeZoneOfsBad),
- kUsedZoneOfsBad = (1 << bUsedZoneOfsBad),
- kEndOfZoneOverwritten = (1 << bEndOfZoneOverwritten),
- kFreeOffsetIncorrect = (1 << bFreeOffsetIncorrect),
- kEndOfZoneFreeOverwritten = (1 << bEndOfZoneFreeOverwritten)
- };
-
- short CheckBlocks(void)
- {
- register ZoneHdrPtr zhp = (ZoneHdrPtr) gAllocQueue.qHead;
- register MemBlkPtr mhp;
- register MemBlkPtr mbp;
- register short blockErrors = 0;
-
- while (!blockErrors && zhp)
- {
- mhp = (MemBlkPtr) ((Ptr) zhp + sizeof(ZoneHeader));
-
- while (!blockErrors && (mhp->blkSize != kEndOfZone))
- {
- if (mhp->blkSize < 0)
- {
- if (mhp->zoneOfs <= 0)
- blockErrors |= kFreeZoneOfsBad;
- mhp = (MemBlkPtr) ((Ptr) mhp - mhp->blkSize);
- }
- else
- {
- if (mhp->zoneOfs >= 0)
- blockErrors |= kUsedZoneOfsBad;
- mhp = (MemBlkPtr) ((Ptr) mhp + mhp->blkSize);
- }
- }
- if (mhp->zoneOfs != -kEndOfZone)
- blockErrors |= kEndOfZoneOverwritten;
- mhp = (MemBlkPtr) ((Ptr) zhp + zhp->nextFreeOfs);
- mbp = nil;
-
- while (!blockErrors && (mhp->blkSize != kEndOfZone))
- {
- if (mhp->blkSize < 0)
- {
- mbp = mhp;
- mhp = (MemBlkPtr) ((Ptr) mhp + mhp->zoneOfs);
- }
- else
- {
- blockErrors |= kFreeOffsetIncorrect;
- break;
- }
- }
- if (mhp->zoneOfs != -kEndOfZone)
- blockErrors |= kEndOfZoneFreeOverwritten;
-
- zhp = (ZoneHdrPtr) zhp->qLink;
- }
-
- return(blockErrors);
- }
-
- #if __DUMPBLOCKS__
- Boolean DumpBlocks(void)
- {
- register ZoneHdrPtr zhp = (ZoneHdrPtr) gAllocQueue.qHead;
- register MemBlkPtr mhp;
- register MemBlkPtr mbp;
- register Boolean blocksOK = true;
-
- printf("\n\nDumpBlocks:\n");
- while (zhp)
- {
- printf("Zone at %08lx:\n", (long) zhp);
- printf("--qLink: %08lx\n--flag: %04x\n--usage: %d\n--freeO: %ld\n--FreeB: %ld\n",
- zhp->qLink, zhp->flag, zhp->usageCounter, zhp->nextFreeOfs, zhp->bytesFree);
-
- mhp = (MemBlkPtr) ((Ptr) zhp + sizeof(ZoneHeader));
-
- while (mhp->blkSize != kEndOfZone)
- {
- if (mhp->blkSize < 0)
- {
- printf(" free block: size %ld\n", -mhp->blkSize);
- if (mhp->zoneOfs <= 0)
- {
- printf("••• Error ••• Offset (%ld) is incorrect!\n", mbp->zoneOfs);
- blocksOK = false;
- }
- mhp = (MemBlkPtr) ((Ptr) mhp - mhp->blkSize);
- }
- else
- {
- printf(" used block: size %ld\n", mhp->blkSize);
- if (mhp->zoneOfs >= 0)
- {
- printf("••• Error ••• Offset (%ld) is incorrect!\n", mbp->zoneOfs);
- blocksOK = false;
- }
- mhp = (MemBlkPtr) ((Ptr) mhp + mhp->blkSize);
- }
- }
- printf("End of zone\n");
- if (mhp->zoneOfs != -kEndOfZone)
- {
- printf("••• Error ••• End of zone has been overwritten!!!\n");
- blocksOK = false;
- }
- mhp = (MemBlkPtr) ((Ptr) zhp + zhp->nextFreeOfs);
- mbp = nil;
-
- while (mhp->blkSize != kEndOfZone)
- {
- if (mhp->blkSize < 0)
- {
- printf(" free block: size %ld\n", -mhp->blkSize);
- mbp = mhp;
- mhp = (MemBlkPtr) ((Ptr) mhp + mhp->zoneOfs);
- }
- else
- {
- blocksOK = false;
- printf("••• Error ••• Offset (%ld) is incorrect!\n", mbp->zoneOfs);
- break;
- }
- }
- printf("End of free blocks!\n");
- if (mhp->zoneOfs != -kEndOfZone)
- {
- printf("••• Error ••• End of zone/free blocks has been overwritten!!!\n");
- blocksOK = false;
- }
-
- zhp = (ZoneHdrPtr) zhp->qLink;
- }
-
- return(blocksOK);
- }
- #endif
-